<?php
// @formatter:off
/**
 * @file WCHolder.abs.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-08-05 00:26:28 +0000 (Mon, 05 Aug 2013) $
 *
 * $Id: WCHolder.abs.php 100 2013-08-05 00:26:28Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0.0.2/includes/holders/WCHolder.abs.php $
 */
// @formatter:on

/**
 * @class WCHolder This is the specification for a generic holder. It holds the
 * logic to manage list of object, preferable WCGTableRepresentation objects
 * indexed by name and id.
 *
 * @warning Every object called item should two basic properties:
 *  - id
 *  - name
 */
abstract class WCHolder {
	/**
	 * @var string This is the class name of the items to be held.
	 */
	protected $_PropertiesItemClass = "";
	/**
	 * @var string This is the fields' prefix in the table where every held
	 * item exists.
	 * It is similar to WCGTableRepresentation::$_PropertiesPrefix
	 */
	protected $_PropertiesPrefix = "";
	/**
	 * @var string This is the table where every held item exists.
	 * It is similar to WCGTableRepresentation::$_PropertiesTable
	 */
	protected $_PropertiesTable = "";
	/**
	 * @var string
	 * @var string This variable holds the name of the column of represented
	 * items' name.
	 * By default, it is 'name'.
	 */
	protected $_PropertiesNameColumn = "name";
	/**
	 * @var boolean This flag indicates if names may be repeated.
	 */
	protected $_PropertiesDupNames = false;
	/**
	 * @var WCConnection Pointer to the global connection object.
	 */
	protected $_db = null;
	/**
	 * @var string Shortcut to database tables prefixes.
	 */
	protected $_dbprefix = "";
	/**
	 * @var array This is the main list where every element is finally held.
	 * This list is organized by two main concepts:
	 * - First, every item will be a sub-list associated with a group id.
	 * - Second, every sub-list will contain two children:
	 *   - One called "byid": associative array between item's id and the
	 *     item itself.
	 *   - Other called "byname": associative array between item's name and
	 *     the item itself.
	 *
	 * @code
	 * array(
	 * 	[group-id] => array(
	 * 		[byid] => array(
	 * 			[id] => ItemClass
	 * 			...
	 * 		)
	 * 		[byname] => array(
	 * 			[name] => ItemClass
	 * 			...
	 * 		)
	 * 	)
	 * 	...
	 * )
	 * @endcode
	 */
	protected $_items = array();
	/**
	 * @var boolean This flag indicates if all represented elements of the
	 * database have been fully loaded.
	 * This is needed to avoid loading and reloading everything when it's not
	 * necessary.
	 */
	protected $_fullLoaded = false;
	/**
	 * Constructor is protected because all holders must be singletons.
	 * Therefore, each subclass have to implement a way to create and call
	 * the sole instance. For example, using something like this:
	 * @code
	 * protected static $_Instance;
	 *
	 * public static function Instance() {
	 * 	if(!isset(self::$_Instance)) {
	 * 		$c = __CLASS__;
	 * 		self::$_Instance = new $c();
	 * 	}
	 *
	 * 	return self::$_Instance;
	 * }
	 * @endcode
	 */
	protected function __construct() {
		//
		// Loading global pointers.
		global $wcDatabaseAccess;
		//
		// Loading shortcuts.
		// @{
		$this->_db = WCConnection::Instance();
		$this->_dbprefix = $wcDatabaseAccess['prefix'];
		// @}
	}
	/**
	 * Class destructor.
	 */
	public function __destruct() {
		unset($this->_items);
	}
	/**
	 * Prevent users to clone the instance.
	 */
	public function __clone() {
		trigger_error(__CLASS__.": Clone is not allowed.", E_USER_ERROR);
	}
	//
	// Public methods.
	// To implement...
	// public function create(...) {
	// public function item($id, ...) {
	// public function itemByName($name, ...) {
	// public function itemIds(...) {
	// public function items(...) {
	/**
	 * This method resets internal list forcing this holder to to reload
	 * everything.
	 */
	public function resetCache() {
		//
		// Removing current items.
		$this->_items = array();
		//
		// Ensuring this holder will reload.
		$this->_fullLoaded = false;
	}
	//
	// Protected methods.
	/**
	 * This method allows to add a fully loaded item into internal lists.
	 *
	 * @param WCRepresentation $item Item to be added.
	 */
	protected function addToCache(&$item) {
		//
		// Checking if internal list have to be created.
		if(!isset($this->_items["byid"])) {
			//
			// Creating lists.
			$this->_items["byid"] = array();
			$this->_items["byname"] = array();
		}
		//
		// Adding item to the list of IDs.
		$this->_items["byid"][$item->id] = $item;
		//
		// Adding item to the list of names.
		eval("\$this->_items[\"byname\"][\$item->{$this->_PropertiesNameColumn}] = \$item;");
	}
	// To implement...
	//protected function findItem($id, ...) {
	//protected function findItemByName($name, ...) {

	//
	// Public class methods.
}
?>